package com.holic.spring.custom;

import com.holic.spring.custom.annotation.GraphQLMapping;
import graphql.com.google.common.collect.ImmutableMap;
import graphql.com.google.common.collect.Maps;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.function.Function;

import static com.holic.spring.custom.annotation.GraphQLMapping.*;

/**
 * @ClassName GraphQLMappingRegistry
 * @Description
 * @Author Neil
 * @Date 2024/11/15 10:49
 * @Version V1.0
 **/
@Component
public class GraphQLMappingDefinitionRegistry {

    private Map<String, GraphQLMappingDefinition> queryDefinitionMap = Maps.newConcurrentMap();
    private Map<String, GraphQLMappingDefinition> mutationDefinitionMap = Maps.newConcurrentMap();
    private Map<String, GraphQLMappingDefinition> subscriptionDefinitionMap = Maps.newConcurrentMap();

    private Map<String, Map<String, GraphQLMappingDefinition>> definitionHolder = ImmutableMap.of(
            QUERY, queryDefinitionMap,
            MUTATION, mutationDefinitionMap,
            SUBSCRIPTION, subscriptionDefinitionMap
    );

    /**
     * 注册GraphQLMappingDefinition
     * @param definition
     */
    public void registerDefinition(GraphQLMappingDefinition definition) {
        Map<String, GraphQLMappingDefinition> definitionMap = definitionHolder.get(definition.getType());
        if(definitionMap.containsKey(definition.getName())){
            throw new IllegalArgumentException("Duplicate GraphQLMapping: " + definition.toString());
        }
        definitionMap.put(definition.getName(), definition);
    }

    /**
     * 根据类型和名称删除GraphQLMappingDefinition
     * @param typeName
     * @param name
     */
    public void removeDefinition(String typeName, String name) {
        Map<String, GraphQLMappingDefinition> definitionMap = definitionHolder.get(typeName);
        definitionMap.remove(name);
    }

    /**
     * 根据类型和名称获取GraphQLMappingDefinition
     * @param typeName
     * @param name
     * @return
     */
    public GraphQLMappingDefinition getDefinition(String typeName, String name) {
        Map<String, GraphQLMappingDefinition> definitionMap = definitionHolder.get(typeName);
        return definitionMap.get(name);
    }

    /**
     * 根据类型和名称判断是否存在GraphQLMappingDefinition
     * @param typeName
     * @param name
     * @return
     */
    public boolean containsBeanDefinition(String typeName, String name){
        Map<String, GraphQLMappingDefinition> definitionMap = definitionHolder.get(typeName);
        return definitionMap.containsKey(name);
    }

    /**
     * 遍历所有的GraphQLMappingDefinition
     * @param callback
     */
    public void doWithEachDefinition(Function<GraphQLMappingDefinition, Void> callback) {
        definitionHolder.forEach((type, definitionMap) -> {
            definitionMap.forEach((name, definition)-> {
                callback.apply(definition);
            });
        });
    }

}
